package com.tencent.wxpay.business;

import com.tencent.wxpay.businessListener.DownloadBillResultListener;
import com.tencent.wxpay.common.Configure;
import com.tencent.wxpay.common.Util;
import com.tencent.wxpay.common.report.ReporterFactory;
import com.tencent.wxpay.common.report.protocol.ReportReqData;
import com.tencent.wxpay.common.report.service.ReportService;
import com.tencent.wxpay.protocol.request.DownloadBillReqData;
import com.tencent.wxpay.protocol.response.DownloadBillResData;
import com.tencent.wxpay.service.DownloadBillService;
import com.thoughtworks.xstream.io.StreamException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 下载对账单服务
 */
public class DownloadBillBusiness {

    private static Logger logger = LoggerFactory.getLogger(DownloadBillBusiness.class);

    /**
     * 运行下载对账单服务
     * @param downloadBillReqData 这个数据对象里面包含了API要求提交的各种数据字段
     * @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件，并做好合理的响应处理
     * @return 若下载失败，则返回DownloadBillResData 结果对象, 若下载成功，则返回下载的纯文本数据，(字符串)
     * @throws Exception
     */
    public static Object run(DownloadBillReqData downloadBillReqData, DownloadBillResultListener resultListener) throws Exception {
        //--------------------------------------------------------------------
        //构造请求“对账单API”所需要提交的数据
        //--------------------------------------------------------------------
        DownloadBillService downloadBillService = new DownloadBillService();
        //API返回的数据
        String downloadBillServiceResponseString;
        // API调用开始时间
        long costTimeStart = System.currentTimeMillis();
        // 发起请求
        downloadBillServiceResponseString = downloadBillService.request(downloadBillReqData);

        // API调用结束时间
        long costTimeEnd = System.currentTimeMillis();
        // API请求耗费时间
        long totalTimeCost = costTimeEnd - costTimeStart;

        logger.info("下载对账单请求总耗时：" + totalTimeCost + "ms");

        logger.info("对账单接口返回的数据如下：");
        logger.info(downloadBillServiceResponseString);

        DownloadBillResData downloadBillResData;

        String returnCode = "";
        String returnMsg = "";
        Object returnObj = null;

        try {
            //注意，这里失败的时候是返回xml数据，成功的时候反而返回非xml数据
            downloadBillResData = (DownloadBillResData) Util.getObjectFromXML(downloadBillServiceResponseString, DownloadBillResData.class);
            if (downloadBillResData == null || downloadBillResData.getReturn_code() == null) {
                logger.error("下载对账单请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问");
                resultListener.onFailByReturnCodeError(downloadBillResData);
                return downloadBillResData;
            }
            if (downloadBillResData.getReturn_code().equals("FAIL")) {
                ///注意：一般这里返回FAIL是出现系统级参数错误，请检测Post给API的数据是否规范合法
                logger.error("下载对账单API系统返回失败，请检测Post给API的数据是否规范合法");
                resultListener.onFailByReturnCodeFail(downloadBillResData);
                returnCode = "FAIL";
                returnMsg = downloadBillResData.getReturn_msg();
                returnObj = downloadBillResData;
            }
        } catch (StreamException e) {
            //注意，这里成功的时候是直接返回纯文本的对账单文本数据，非XML格式
            if (downloadBillServiceResponseString.equals(null) || downloadBillServiceResponseString.equals("")) {
                logger.error("下载对账单接口返回数据为空");
                resultListener.onDownloadBillFail(downloadBillServiceResponseString);
            } else {
                logger.info("下载对账单接口成功返回数据");
                resultListener.onDownloadBillSuccess(downloadBillServiceResponseString);
            }
            returnCode = "SUCCESS";
            returnObj = downloadBillServiceResponseString;
        } finally {
            //是否发送统计请求
            if(Configure.isReport()){
                ReportReqData reportReqData = new ReportReqData(
                    downloadBillReqData.getDevice_info(),
                    Configure.DOWNLOAD_BILL_API,
                    (int) (totalTimeCost),//本次请求耗时
                    returnCode,
                    returnMsg,
                    "",
                    "",
                    "",
                    "",
                    Configure.getIP()
                );
                long timeAfterReport;
                // 判断是否异步发送
                if(Configure.isUseThreadToDoReport()){
                    ReporterFactory.getReporter(reportReqData).run();
                    timeAfterReport = System.currentTimeMillis();
                    logger.info("downloadBill+report总耗时（异步方式上报）："+(timeAfterReport-costTimeStart) + "ms");
                }else{
                    ReportService.request(reportReqData);
                    timeAfterReport = System.currentTimeMillis();
                    logger.info("downloadBill+report总耗时（同步方式上报）："+(timeAfterReport-costTimeStart) + "ms");
                }
            }
        }
        return returnObj;
    }
}
